package com.newsappserver.userservice.service;

import com.newsappserver.userservice.defines.AppException;
import com.newsappserver.userservice.defines.ErrorCode;
import com.newsappserver.userservice.defines.UserRole;
import com.newsappserver.userservice.dto.request.UserCreateRequest;
import com.newsappserver.userservice.dto.request.UserUpdateRequest;
import com.newsappserver.userservice.dto.response.ApiResponse;
import com.newsappserver.userservice.dto.response.IntrospectResponse;
import com.newsappserver.userservice.dto.response.UserResponse;
import com.newsappserver.userservice.entity.Timestamps;
import com.newsappserver.userservice.entity.UserEntity;
import com.newsappserver.userservice.mapper.UserMapper;
import com.newsappserver.userservice.repository.UserRepository;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class UserService {
    UserRepository userRepository;
    UserMapper userMapper;

    PasswordEncoder passwordEncoder;

    // 创建用户
    // test by httpie: http POST :8080/api/user/register name=root username=root email=1690544550@qq.com password=12345678
    public UserResponse userCreate(UserCreateRequest userCreateRequest) {
        if (userRepository.existsByUsername(userCreateRequest.getUsername())) {
            throw new AppException(ErrorCode.USER_EXISTED); // 抛出用户已存在异常
        }

        UserEntity userEntity = userMapper.toUser(userCreateRequest);
        userEntity.setPassword(passwordEncoder.encode(userCreateRequest.getPassword()));

        HashSet<String> role = new HashSet<>();
        role.add(UserRole.USER.name()); // 添加角色

        userEntity.setRoles(role);

        userEntity.setTimestamps(Timestamps
                .builder()
                .createdAt(LocalDateTime.now())
                .updatedAt(LocalDateTime.now())
                .build()
        );
        // 保存用户
        return userMapper.toUserResponse(userRepository.save(userEntity));
    }

    // 需要管理员角色才能获取所有账户
    @PreAuthorize("hasRole('ADMIN')")
    public List<UserResponse> getAllUsers() {
        log.info("Api Watch: getAllUsers");

        return userRepository
                .findAll()
                .stream()
                .map(userMapper::toUserResponse)
                .toList();
    }

    // 获取用户自己的信息
    public UserResponse getUserOwnerInfo() {
        var context = SecurityContextHolder.getContext();
        String name = context.getAuthentication().getName();

        UserEntity userEntity = userRepository
                .findByUsername(name)
                .orElseThrow(() -> new AppException(ErrorCode.NOT_FOUND)); // 没找到

        return userMapper.toUserResponse(userEntity);
    }

    // 在认证之后，根据用户id来找到用户
    @PostAuthorize("returnObject.username == authentication.name")
    public UserResponse getUserById(Long userId) {
        return userMapper.toUserResponse(userRepository.findById(userId).orElseThrow(
                () -> new AppException(ErrorCode.NOT_FOUND)
        ));
    }

    // 更新用户
    public UserResponse updateUser(UserUpdateRequest userUpdateRequest, Long userId) {
        UserEntity currentUser = userRepository.findById(userId)
                .orElseThrow(() -> new AppException(ErrorCode.NOT_FOUND));

        LocalDateTime createdAt = currentUser.getTimestamps().getCreatedAt();

        log.info("Api Watch: updateUser");
        log.info("Api Watch: Name: {}", currentUser.getUsername());
        log.info("Api Watch: Email: {}", currentUser.getEmail());
        log.info("Api Watch: Password: {}", currentUser.getPassword());

        // 更新账户
        userMapper.updateUser(currentUser, userUpdateRequest);
        currentUser.setPassword(passwordEncoder.encode(userUpdateRequest.getPassword()));
        currentUser.setTimestamps(Timestamps.builder()
                .createdAt(createdAt)
                .updatedAt(LocalDateTime.now())
                .build()
        );

        log.info("Api Watch: after updateUser");
        log.info("Api Watch: Name: {}", currentUser.getUsername());
        log.info("Api Watch: Email: {}", currentUser.getEmail());
        log.info("Api Watch: Password: {}", currentUser.getPassword());
        // 保存已更新
        return userMapper.toUserResponse(userRepository.save(currentUser));
    }

    @Modifying // 表示会修改数据库
    public IntrospectResponse deleteUserById(Long userId) {
        try {
            UserEntity currentUser = userRepository.findById(userId)
                    .orElseThrow(() -> new AppException(ErrorCode.NOT_FOUND));

            if (currentUser != null) {
                userRepository.deleteById(userId);
                return IntrospectResponse.builder()
                        .valid(true) // 合法删除
                        .build();
            } else {
                throw new AppException(ErrorCode.NOT_FOUND);
            }
        } catch (DataAccessException exception) {
            throw new AppException(ErrorCode.DATABASE_ERROR);
        }
    }
}
